package com.sys.basics.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sys.basics.config.annotation.SysLogAnnotation;
import com.sys.basics.config.jsonRes.JsonResult;
import com.sys.basics.entity.SysUser;
import com.sys.basics.service.SysUserService;
import com.sys.basics.utils.CryptoUtils;
import com.sys.basics.utils.ShiroUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.util.HashMap;

@Validated
@Slf4j
@Api(tags = "认证")
@RestController
@RequestMapping("/basics/auth")
public class AuthController {
    protected JsonResult result = new JsonResult();

    @Value("${kaptcha.image.width}")
    private int kaptchaImageWidth;

    @Value("${kaptcha.image.height}")
    private int kaptchaImageHeight;

    @Value("${kaptcha.session.key}")
    private String kaptchaSessionKey;

    @Autowired
    SysUserService sysUserService;

    @ApiOperation("用户注册")
    @PostMapping("/register")
    public JsonResult register(@RequestBody @Valid SysUser user) {
        String pwd = user.getPassword();
        if(StringUtils.isBlank(user.getUsername())){
            return result.error("账号不能为空");
        }
        if(StringUtils.isBlank(pwd)){
            return result.error("密码不能为空");
        }
        HashMap<String, String> pwdHashMap = CryptoUtils.saltEncrypt(pwd);
        user.setSalt(pwdHashMap.get("salt"));
        user.setPassword(pwdHashMap.get("password"));
        boolean rsg = sysUserService.save(user);
        if (rsg) {
            result.success("注册成功");
        } else {
            result.error("注册失败！");
        }
        return result;
    }

    @ApiOperation("用户登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", required = true, value = "账号", paramType = "query"),
            @ApiImplicitParam(name = "password", required = true, value = "密码", paramType = "query"),
            @ApiImplicitParam(name = "code", required = true, value = "验证码", paramType = "query")
    })
    @GetMapping("/login")
    public JsonResult login(HttpServletRequest request,
                            @NotEmpty(message = "用户名不能为空") String username,
                            @NotEmpty(message = "密码不能为空") String password,
                            @NotEmpty(message = "验证码不能为空") String code) {
        //校验验证码
         Object kaptchaSessionCode = request.getSession().getAttribute(kaptchaSessionKey);
        if(StringUtils.isBlank((String)kaptchaSessionCode)) {
            return result.error("验证码过期，请刷新验证码！");
        }
        if (!code.equalsIgnoreCase(String.valueOf(kaptchaSessionCode))) {
            return result.error("验证码错误！");
        }
        SysUser currentUser = sysUserService.getByAccount(username);
        if (ObjectUtil.isNull(currentUser)) {
            return result.error("账号不存在！");
        }
        request.getSession().removeAttribute(kaptchaSessionKey);

        //shiro认证登录
        Subject subject = ShiroUtils.getSubject();
        //使用用户id做token认证
        UsernamePasswordToken token = new UsernamePasswordToken(currentUser.getId().toString(), password);
        try {
            subject.login(token);
        } catch (IncorrectCredentialsException ice) {
            return result.error("密码不正确");
        } catch (DisabledAccountException dsae) {
            return result.error("账号被禁用");
        } catch (AuthenticationException ae) {
            return result.error("状态不正常");
        }
        if (subject.isAuthenticated()) {
            return result.success("登录成功");
        } else {
            token.clear();
            ShiroUtils.getSession().removeAttribute("userInfo");
            return result.error("登录失败");
        }
    }

    @ApiOperation("退出登录")
    @PostMapping("/logout")
    public void logout() {

    }


    @ApiOperation("获取图片验证码")
    @GetMapping("/kaptcha")
    public void kaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");

//        LineCaptcha kaptcha = CaptchaUtil.createLineCaptcha(kaptchaImageWidth, kaptchaImageHeight);
//        CircleCaptcha kaptcha = CaptchaUtil.createCircleCaptcha(kaptchaImageWidth, kaptchaImageHeight);
        ShearCaptcha kaptcha = CaptchaUtil.createShearCaptcha(kaptchaImageWidth, kaptchaImageHeight);

        // 将生成的验证码字符串保存到 session 中
        String kaptchaText = kaptcha.getCode();
        request.getSession().setAttribute(kaptchaSessionKey, kaptchaText);
        log.info("生成的验证码是: {}", kaptchaText);

        // 将生成的验证码图片向客户端写出
        ServletOutputStream out = response.getOutputStream();
        kaptcha.write(out);
        out.flush();
    }
}
